home *** CD-ROM | disk | FTP | other *** search
- #include <windows.h>
- #include <mmsystem.h>
- #include "tblt.h"
-
- #define DSNA 0x00220326L // the magical ROP
-
- BOOL FAR PASCAL doTransBlit(HDC hDC, int x, int y, int dx, int dy,
- HBITMAP hBitmap0, BITMAP FAR * lpBitmap, int x0, int y0,
- HBITMAP FAR * lphBitmapMask, COLORREF transColor, DWORD dwFlags)
- {
- static bTrans=-23; // magic value for init compare
- RECT rc;
-
- HDC hImageDC=NULL;
- HDC hMaskDC=NULL;
- HDC tempDC=NULL;
-
- HANDLE hOldObj=NULL;
-
- HBITMAP hBitmapMask=NULL;
- HBITMAP hOBitmapMask=NULL;
- HBITMAP hOBitmapImage=NULL;
- HBITMAP tempBit=NULL;
- BOOL fMask;
- BOOL fScreen;
- WORD xOff, yOff;
-
- if(!hDC || !hBitmap0)
- return FALSE;
-
- if(bTrans==-23 || dwFlags & TRANS_FORCECALCCAPS)
- bTrans = GetDeviceCaps(hDC, CAPS1) & C1_TRANSPARENT;
-
- fMask=(dwFlags&TRANS_SAVEMASK)!=0;
- fScreen=(dwFlags&TRANS_FORCESCREEN)!=0;
-
- if(!dx) // if none provided, assume full bitmap
- dx=lpBitmap->bmWidth;
- if(!dy) // if none provided, assume full bitmap
- dy=lpBitmap->bmHeight;
-
- if((x0+dx) >lpBitmap->bmWidth)
- return FALSE;
-
- if((y0+dy) >lpBitmap->bmHeight)
- return FALSE;
-
- if ( (lpBitmap->bmPlanes==1) && (lpBitmap->bmBitsPixel==1) )
- {
- // If mono source, do it in one ROP....
-
- hImageDC = CreateCompatibleDC(hDC);
- if(!hImageDC)
- goto error;
-
- hOBitmapImage=SelectObject(hImageDC, hBitmap0);
-
- BitBlt(hDC, x, y, dx, dy, hImageDC, x0, y0, SRCPAINT);
-
- SelectObject(hImageDC,hOBitmapImage);
- DeleteDC(hImageDC);
-
- return TRUE;
- }
-
- if(bTrans && !(dwFlags & TRANS_FORCEOLD))
- {
- // if it is available and they don't tell us not to use it...
-
- if(!(dwFlags & TRANS_NOSAVEDC))
- SaveDC(hDC);
-
- SetBkColor(hDC, transColor);
- SetBkMode(hDC, NEWTRANSPARENT);
-
- // Get source image...
- hImageDC = CreateCompatibleDC(hDC);
- if(!hImageDC)
- goto error;
-
- hOBitmapImage=SelectObject(hImageDC, hBitmap0);
-
-
- BitBlt (hDC, x, y, dx, dy, hImageDC,
- x0, y0,SRCCOPY);
-
- SelectObject(hImageDC, hOBitmapImage);
- DeleteDC(hImageDC);
-
- if(!(dwFlags & TRANS_NOSAVEDC))
- RestoreDC(hDC,-1);
- return TRUE;
- }
- else
- {
-
- if(!(dwFlags & TRANS_NOSAVEDC))
- SaveDC(hDC);
-
- hImageDC = CreateCompatibleDC(hDC);
- hMaskDC = CreateCompatibleDC(hDC);
- if(!hImageDC || !hMaskDC)
- goto error;
-
- hOBitmapImage=SelectObject(hImageDC, hBitmap0);
-
- // We can optimize speed more by saving mask bitmap instead of
- // re-creating it every time, but this takes up more memory
-
- // this only helps if the driver does not support transparent blits
- // directly.
-
- if(lphBitmapMask)
- hBitmapMask=*lphBitmapMask;
- else
- hBitmapMask=0;
-
- if(!fMask && hBitmapMask)
- {
- // an old one was floating around...
- DeleteObject(hBitmapMask);
- hBitmapMask=NULL;
- *lphBitmapMask=NULL;
- }
-
- if(!hBitmapMask)
- {
- // note: we create mask for entire bitmap, even if we
- // only want to use part of it. This makes sense
- // if we are using 'tiled' bitmaps (see GRAPHX technote)
- // and we are saving the mask bitmap.
-
- hBitmapMask = CreateBitmap(lpBitmap->bmWidth, lpBitmap->bmHeight, 1, 1, NULL);
- hOBitmapMask=SelectObject(hMaskDC, hBitmapMask);
-
- // set background color for color-to-mono conversion
- // (bk color will be white(1), all else is black (0) )
- SetBkColor(hImageDC, transColor);
-
- BitBlt(hMaskDC, 0, 0, lpBitmap->bmWidth, lpBitmap->bmHeight,
- hImageDC, 0, 0, SRCCOPY);
-
- // invert 1s and 0s to get valid mask..(could also use
- // bitblt() and DSTINVERT ROP
- rc.left=rc.top=0;
- rc.right=lpBitmap->bmWidth;
- rc.bottom=lpBitmap->bmHeight;
- InvertRect(hMaskDC,&rc);
-
- #ifdef MASKDEBUG
- BitBlt(hDC, 0, 0, lpBitmap->bmWidth, lpBitmap->bmHeight,
- hMaskDC, 0, 0, SRCCOPY);
- #endif
- }
- else
- {
- // re-use mask bitmap from last time.
-
- hOBitmapMask=SelectObject(hMaskDC, hBitmapMask);
-
- #ifdef MASKDEBUG
- BitBlt(hDC, 0, 0, lpBitmap->bmWidth, lpBitmap->bmHeight,
- hMaskDC, 0, 0, SRCCOPY);
- #endif
- }
- // now we have mask bitmap: we can continue
-
- if(!fScreen)
- {
- // Do work off-screen so we don't see flash of INVERTS
- // This is a little slower (but if you're keeping an off-screen
- // bitmap of the screen anyway you should use it)
-
- tempDC = CreateCompatibleDC (hDC);
- tempBit = CreateCompatibleBitmap(hDC, dx, dy);
- hOldObj = SelectObject (tempDC, tempBit);
-
- // copy what's on the screen first
- BitBlt (tempDC, 0, 0, dx, dy, hDC, x, y, SRCCOPY);
- xOff=0;
- yOff=0;
- }
- else
- {
- // for 'old' way:
- // MAYBE faster, definitely saves memory, but very much uglier.
- // it might not be faster because system-memory operations
- // are usually faster than screen-memory operations
- // (see the Graphics Design Technote)
- // saves memory 'cause no temp DC and bitmap
- // uglier 'cause operations are visible and flash
-
- // for 'new' way: (if supported)
- // faster, not ugly, some memory savings
- // faster 'cause no extra time for copying temp bitmap
- // saves memory 'cause no temp DC and bitmap
-
- tempDC=hDC; // do work directly on target DC (screen)
- xOff=x;
- yOff=y;
- }
-
- // these three blits do the work...
-
- BitBlt(tempDC, xOff, yOff, dx, dy,
- hImageDC, x0, y0, SRCINVERT);
-
- BitBlt(tempDC, xOff, yOff, dx, dy,
- hMaskDC, x0, y0, DSNA);
-
- BitBlt(tempDC, xOff, yOff, dx, dy,
- hImageDC, x0, y0, SRCINVERT);
-
- if(!fScreen)
- {
- // put it all on the target device
-
- BitBlt (hDC, x, y, dx, dy, tempDC,
- 0, 0,SRCCOPY);
-
- // clean up off-screen bitmaps
- SelectObject(tempDC, hOldObj);
- DeleteDC(tempDC);
- DeleteObject(tempBit);
-
- } // else it is already there...
-
- SelectObject(hMaskDC, hOBitmapMask);
- DeleteDC(hMaskDC);
-
- SelectObject(hImageDC, hOBitmapImage);
- DeleteDC(hImageDC);
-
- if(!fMask)
- {
- DeleteObject(hBitmapMask);
- hBitmapMask=NULL;
- }
- else if(lphBitmapMask)
- *lphBitmapMask=hBitmapMask;
-
- if(!(dwFlags & TRANS_NOSAVEDC))
- RestoreDC(hDC,-1);
- return TRUE;
- }
- error:
- if(tempDC)
- {
- if(hOldObj)
- SelectObject(tempDC, hOldObj);
- DeleteDC(tempDC);
- }
- if(hMaskDC)
- {
- if(hOBitmapMask)
- SelectObject(hMaskDC, hOBitmapMask);
- DeleteDC(hMaskDC);
- }
- if(hImageDC)
- {
- if(hOBitmapImage)
- SelectObject(hImageDC, hOBitmapImage);
- DeleteDC(hImageDC);
- }
- if(tempBit)
- DeleteObject(tempBit);
- if(hBitmapMask)
- DeleteObject(hBitmapMask);
- if(lphBitmapMask)
- *lphBitmapMask=0;
- return FALSE;
-
- }
-